// /*
//  * Copyright 2018 Google Inc.
//  *
//  * Use of this source code is governed by a BSD-style license that can be
//  * found in the LICENSE file.
//  */
//
// #include "include/utils/SkAnimCodecPlayer.h"
//
// #include "include/codec/SkCodec.h"
// #include "include/codec/SkEncodedOrigin.h"
// #include "include/core/SkAlphaType.h"
// #include "include/core/SkBlendMode.h"
// #include "include/core/SkCanvas.h"
// #include "include/core/SkData.h"
// #include "include/core/SkImage.h"
// #include "include/core/SkImageInfo.h"
// #include "include/core/SkMatrix.h"
// #include "include/core/SkPaint.h"
// #include "include/core/SkRefCnt.h"
// #include "include/core/SkSamplingOptions.h"
// #include "include/core/SkSize.h"
// #include "include/core/SkTypes.h"
// // #include "src/codec/SkCodecImageGenerator.h"
//
// #include <algorithm>
// #include <cstddef>
// #include <memory>
// #include <utility>
// #include <vector>
//
//
//
// SkAnimCodecPlayer::SkAnimCodecPlayer(sk_sp<SkImage> decoder) : fCodec(std::move(codec)) {
//     fImageInfo = fCodec->getInfo();
//     fFrameInfos = fCodec->getFrameInfo();
//     fImages.resize(fFrameInfos.size());
//
//     // change the interpretation of fDuration to a end-time for that frame
//     size_t dur = 0;
//     for (auto& f : fFrameInfos) {
//         dur += f.fDuration;
//         f.fDuration = dur;
//     }
//     fTotalDuration = dur;
//
//     if (!fTotalDuration) {
//         // Static image -- may or may not have returned a single frame info.
//         fFrameInfos.clear();
//         fImages.clear();
//         fImages.push_back(SkImages::DeferredFromGenerator(
//                 SkCodecImageGenerator::MakeFromCodec(std::move(fCodec))));
//     }
// }
//
// SkAnimCodecPlayer::~SkAnimCodecPlayer() {}
//
// SkISize SkAnimCodecPlayer::dimensions() const {
//     if (!fCodec) {
//         auto image = fImages.front();
//         return image ? image->dimensions() : SkISize::MakeEmpty();
//     }
//     if (SkEncodedOriginSwapsWidthHeight(fCodec->getOrigin())) {
//         return { fImageInfo.height(), fImageInfo.width() };
//     }
//     return { fImageInfo.width(), fImageInfo.height() };
// }
//
// sk_sp<SkImage> SkAnimCodecPlayer::getFrameAt(int index) {
//     SkASSERT((unsigned)index < fFrameInfos.size());
//
//     if (fImages[index]) {
//         return fImages[index];
//     }
//
//     size_t rb = fImageInfo.minRowBytes();
//     size_t size = fImageInfo.computeByteSize(rb);
//     auto data = SkData::MakeUninitialized(size);
//
//     SkCodec::Options opts;
//     opts.fFrameIndex = index;
//
//     const auto origin = fCodec->getOrigin();
//     const auto orientedDims = this->dimensions();
//     const auto originMatrix = SkEncodedOriginToMatrix(origin, orientedDims.width(),
//                                                               orientedDims.height());
//
//     SkPaint paint;
//     paint.setBlendMode(SkBlendMode::kSrc);
//
//     auto imageInfo = fImageInfo;
//     if (fFrameInfos[index].fAlphaType != kOpaque_SkAlphaType && imageInfo.isOpaque()) {
//         imageInfo = imageInfo.makeAlphaType(kPremul_SkAlphaType);
//     }
//     const int requiredFrame = fFrameInfos[index].fRequiredFrame;
//     if (requiredFrame != SkCodec::kNoFrame && fImages[requiredFrame]) {
//         auto requiredImage = fImages[requiredFrame];
//         auto canvas = SkCanvas::MakeRasterDirect(imageInfo, data->writable_data(), rb);
//         if (origin != kDefault_SkEncodedOrigin) {
//             // The required frame is stored after applying the origin. Undo that,
//             // because the codec decodes prior to applying the origin.
//             // FIXME: Another approach would be to decode the frame's delta on top
//             // of transparent black, and then draw that through the origin matrix
//             // onto the required frame. To do that, SkCodec needs to expose the
//             // rectangle of the delta and the blend mode, so we can handle
//             // kRestoreBGColor frames and Blend::kSrc.
//             SkMatrix inverse;
//             SkAssertResult(originMatrix.invert(&inverse));
//             canvas->concat(inverse);
//         }
//         canvas->drawImage(requiredImage, 0, 0, SkSamplingOptions(), &paint);
//         opts.fPriorFrame = requiredFrame;
//     }
//
//     if (SkCodec::kSuccess != fCodec->getPixels(imageInfo, data->writable_data(), rb, &opts)) {
//         return nullptr;
//     }
//
//     auto image = SkImages::RasterFromData(imageInfo, std::move(data), rb);
//     if (origin != kDefault_SkEncodedOrigin) {
//         imageInfo = imageInfo.makeDimensions(orientedDims);
//         rb = imageInfo.minRowBytes();
//         size = imageInfo.computeByteSize(rb);
//         data = SkData::MakeUninitialized(size);
//         auto canvas = SkCanvas::MakeRasterDirect(imageInfo, data->writable_data(), rb);
//         canvas->concat(originMatrix);
//         canvas->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
//         image = SkImages::RasterFromData(imageInfo, std::move(data), rb);
//     }
//     return fImages[index] = image;
// }
//
// sk_sp<SkImage> SkAnimCodecPlayer::getFrame() {
//     SkASSERT(fTotalDuration > 0 || fImages.size() == 1);
//
//     return fTotalDuration > 0
//         ? this->getFrameAt(fCurrIndex)
//         : fImages.front();
// }
//
// bool SkAnimCodecPlayer::seek(uint32_t msec) {
//     if (!fTotalDuration) {
//         return false;
//     }
//
//     msec %= fTotalDuration;
//
//     auto lower = std::lower_bound(fFrameInfos.begin(), fFrameInfos.end(), msec,
//                                   [](const SkCodec::FrameInfo& info, uint32_t msec) {
//                                       return (uint32_t)info.fDuration <= msec;
//                                   });
//     int prevIndex = fCurrIndex;
//     fCurrIndex = lower - fFrameInfos.begin();
//     return fCurrIndex != prevIndex;
// }
//
//
